#!/usr/bin/env python
# coding: utf-8
"""
python system_mac_config.py --set "enable" --check "enable"    #query all mac, log unexpexted mac, and set system mac with inventory mac.
python system_mac_config.py --set "enable" --check "disable"   #query all mac, and set system mac with inventory mac.
python system_mac_config.py --set "disable" --check "enable"   #query all mac, and log unexpected mac.
python system_mac_config.py --set "disable" --check "disable"  #query all mac.
"""

import re
import os
import time
import datetime
import string
from onshs.ne.tnxxx.tnxxxcfg_basecase import *

log_node_prefix = "systemmac"
log_node_summary = log_node_prefix+r"_summary"
log_node_fail = log_node_prefix+r"_fail"
log_node_success = log_node_prefix+r"_success"
log_node_warning = log_node_prefix+r"_warning"

log_file_notexisted_fail = "the file:%s isn't existed\n"
log_connect_fail = "connect ip:%s failed\n"
log_mac_verify_fail = "verify ip:%s inventory mac and console mac failed\n"
log_get_master_opca_fail = "get ip:%s master opca failed\n"
log_get_system_mac_fail = "get ip:%s system mac failed\n"
log_get_inventory_mac_fail = "get ip:%s inventory mac failed\n"
log_get_console_mac_fail = "get ip:%s console mac failed\n"
log_get_zebos_mac_fail = "get ip:%s zebos mac failed\n"
log_get_dynamic_lacp_fail = "get ip:%s dynamic lacp failed\n"
log_dynamic_lacp_notexisted_fail = "ip:%s dynamic lacp is existed\n"
log_set_system_mac_fail = "set ip:%s system mac failed\n"

log_master_opca_success = "ip:%s master opca is %d\n"
log_system_mac_success = "ip:%s system mac is:%s\n"
log_inventory_mac_success = "ip:%s inventory mac is:%s\n"
log_console_mac_success = "ip:%s console mac is:%s\n"
log_zebos_mac_success = "ip:%s zebos mac is:%s\n"
log_dynamic_lacp_notexisted_success = "ip:%s dynamic lacp isn't existed\n"
log_set_system_mac_success = "ip:%s set system mac:%s success\n"

log_system_mac_is_zero_warning = "ip:%s system mac is 00:00:00:00:00:00 or 00:00:00:00:00:01"
log_inventory_mac_isnot_utptn_warning = "ip:%s inventoy mac isn't begin with 00:07:ba"
log_console_mac_isnot_utptn_warning = "ip:%s console mac isn't begin with 00:07:ba"
log_inventory_and_console_mac_difference_isnot_1_warning = "ip:%s the difference between inventory mac and console mac isn't equal to 1"

log_summary_success = "ip:%s system mac success"
log_summary_fail = "ip:%s system mac failed"


class TestCase(TnxxxCfg_BaseCase):
    """
    TestCase
    """
    OPTIONS = [
        {
            'opt' : '--cfgfile',
            'dest': 'cfgfile',
            'metavar' : 'CFGFILE',
            'help' : 'the file of ip list configuration',
            'required' : False,
            'default' : "ip.txt"
        },
        {
            'opt' : '--set',
            'dest': 'set',
            'metavar' : 'SET',
            'help' : 'the configuration of set system mac',
            'required' : False,
            'default' : "enable"
        },
        {
            'opt' : '--check',
            'dest': 'check',
            'metavar' : 'CHECK',
            'help' : 'the configuration of check unexpected system mac,inventory mac,console mac',
            'required' : False,
            'default' : "enable"
        }, 
    ]     
    
    def info_init(self):
        self.info_dic = {}     
              
        return True 
    
    #以node为关键字，把信息保存到info_dic[node]中。
    def info_show(self, node, info):
        node = self.set + r'_' + node
        if not self.info_dic.has_key(node):
            self.info_dic[node] = ""
        self.info_dic[node] += info + '\n'        
        return True    
            
    def info_file_save(self, ip):
        path = os.getcwd()+'//'
        
        for node in self.info_dic:
            info_list = open(path+node+'_'+self.worktime+'.txt','a')            
            info_list.write(self.info_dic[node])
            info_list.close()
            
        return True
    
    def get_iplist(self):
        iplist_filted = []                
        if os.path.isfile(os.getcwd()+r'/'+ self.iplistfile):
            iplist = open(os.getcwd()+r'/'+ self.iplistfile)            
        else:
            self.info_show(log_node_fail, log_file_notexisted_fail%(self.iplistfile))            
            return iplist_filted 
        
        for line in iplist:
            if re.match(r'^\s*$', line) is not None : continue # 忽略空白行
            if re.match(r'^\s*#', line) is not None : continue # 忽略注释行            
            iplist_filted.append(line.strip('\n'))        
            
        iplist.close()
        
        return iplist_filted
        
    def get_master_opca(self):
        query_masterppc_cmd = '''$.dbgcli.0.Cmd "queryasyn valid 1, NeStat, (MasterPPC), *"'''
        rtn_str = None        
        rtn_str = self.tnxxx.send_rtn_str(query_masterppc_cmd, self.get_ne_ip(0), 0, MTN_PORT)
        if [] == re.findall('success', rtn_str) or [] == re.findall('\d',rtn_str):         
            self.info_show(log_node_fail, log_get_master_opca_fail%(self.get_ne_ip(0)))
            self.info_show(log_node_summary, log_summary_fail%(self.get_ne_ip(0)))
            return False
        else:            
            self.master_opca = int(re.findall('\d',rtn_str)[0])
            self.info_show(log_node_success, log_master_opca_success%(self.get_ne_ip(0),self.master_opca))           
            return True 
    
    def get_system_mac(self):
        query_cmd = '''$.dbgcli.0.Cmd "queryasyn valid 1, LsrCfg, (SysMac), *"'''
        rtn_str = None       
        rtn_str = self.tnxxx.send_rtn_str(query_cmd, self.get_ne_ip(0), 0, MTN_PORT)
        if [] == re.findall('success', rtn_str):         
            self.info_show(log_node_fail, log_get_system_mac_fail%(self.get_ne_ip(0)))
            self.info_show(log_node_summary, log_summary_fail%(self.get_ne_ip(0)))
            return False
        else:
            system_mac_list = re.findall('\d+[,\r]',rtn_str)
        
        #convert to str "AABBCCDDEEFF" format.        
        for macbyte in system_mac_list:
            if 1 == len(str(hex(int(macbyte[:len(macbyte)-1])))[2:]):
                self.system_mac += "0"+str(hex(int(macbyte[:len(macbyte)-1])))[2:]
            else:
                self.system_mac += str(hex(int(macbyte[:len(macbyte)-1])))[2:]
        
        self.info_show(log_node_success, log_system_mac_success%(self.get_ne_ip(0),self.system_mac))   
            
        return True
    
    def get_inventory_mac(self):
        if 3 == self.master_opca:
            query_cmd = '''$.necli.0.CmdEx "ExtInventoryRead" {{Octet,3},{ULong,256}}'''
        else:
            query_cmd = '''$.necli.0.CmdEx "ExtInventoryRead" {{Octet,4},{ULong,256}}'''
            
        rtn_str = None       
        rtn_str = self.tnxxx.send_rtn_str(query_cmd, self.get_ne_ip(0), 0, MTN_PORT)
        if [] == re.findall('success', rtn_str) or [] == re.findall('MAC:01\w+',rtn_str):         
            self.info_show(log_node_fail, log_get_inventory_mac_fail%(self.get_ne_ip(0)))
            self.info_show(log_node_summary, log_summary_fail%(self.get_ne_ip(0)))
            return False
        else:
            #convert to str "AABBCCDDEEFF" format.
            self.inventory_mac = re.findall('MAC:01\w+',rtn_str)[0][6:]            
            self.info_show(log_node_success, log_inventory_mac_success%(self.get_ne_ip(0),self.inventory_mac.lower()))
            return True
            
    def get_console_mac(self):        
        query_cmd = '*(0xd0000008)'
        rtn_str = None       
        rtn = self.tnxxx.send_rtn_str(query_cmd, self.get_ne_ip(0), 0, DEV_PORT)
        if [] == re.findall('value', rtn):
            self.info_show(log_node_fail, log_get_console_mac_fail%(self.get_ne_ip(0)))
            self.info_show(log_node_summary, log_summary_fail%(self.get_ne_ip(0)))
            return False
        rtn_str = re.findall(r'= 0x\w+',rtn)[0][4:]
        
        mac_0123 = "0"*(8-len(rtn_str)) + rtn_str     
        
        query_cmd = '*(0xd000000c)'
        rtn_str = None       
        rtn = self.tnxxx.send_rtn_str(query_cmd, self.get_ne_ip(0), 0, DEV_PORT)
        if [] == re.findall('value', rtn):
            self.info_show(log_node_fail, log_get_console_mac_fail%(self.get_ne_ip(0)))
            self.info_show(log_node_summary, log_summary_fail%(self.get_ne_ip(0)))
            return False
        rtn_str = re.findall(r'= 0x\w+',rtn)[0][4:]
        
        mac_45_raw = "0"*(8-len(rtn_str)) + rtn_str
        mac_45 = mac_45_raw[:4]
                
        #convert to str "AABBCCDDEEFF" format.
        self.console_mac = mac_0123 + mac_45
        self.info_show(log_node_success, log_console_mac_success%(self.get_ne_ip(0),self.console_mac))
        return True
    
    def get_zebos_mac(self):
        query_cmd = "show lacp sys-id"
        rtn_str = None       
        rtn_str = self.tnxxx.send_rtn_str(query_cmd, self.get_ne_ip(0), 0, ZEBOS_PORT)
        if [] == re.findall('System', rtn_str) or [] == re.findall(',[\w-]+',rtn_str):         
            self.info_show(log_node_fail, log_get_zebos_mac_fail%(self.get_ne_ip(0)))
            self.info_show(log_node_summary, log_summary_fail%(self.get_ne_ip(0)))
            return False
        else:
            zebos_mac = re.findall(',[\w-]+',rtn_str)[0][1:]
        
        self.info_show(log_node_success, log_zebos_mac_success%(self.get_ne_ip(0),zebos_mac))   
            
        return True
    
    def check_unexpected_mac(self):
        if "000000000000" == self.system_mac or "000000000001" == self.system_mac:
            self.info_show(log_node_warning, log_system_mac_is_zero_warning%(self.get_ne_ip(0)))
        if "0007ba" != self.inventory_mac.lower()[:6]:
            self.info_show(log_node_warning, log_inventory_mac_isnot_utptn_warning%(self.get_ne_ip(0)))
        if "0007ba" != self.console_mac.lower()[:6]:
            self.info_show(log_node_warning, log_console_mac_isnot_utptn_warning%(self.get_ne_ip(0)))
        if string.atoi(self.inventory_mac.lower()[4:],16) != string.atoi(self.console_mac.lower()[4:],16)-1:
            self.info_show(log_node_warning, log_inventory_and_console_mac_difference_isnot_1_warning%(self.get_ne_ip(0)))
            
        return True
    
    def if_dynamic_trunk_notexisted(self):
        query_cmd = '''$.dbgcli.0.Cmd "queryasyn valid 1, TrunkIfCfg, (TrunkMode), TrunkMode=1"'''
        rtn_str = None       
        rtn_str = self.tnxxx.send_rtn_str(query_cmd, self.get_ne_ip(0), 0, MTN_PORT)
        if [] == re.findall('success', rtn_str):         
            self.info_show(log_node_fail, log_get_dynamic_lacp_fail%(self.get_ne_ip(0)))
            self.info_show(log_node_summary, log_summary_fail%(self.get_ne_ip(0)))
            return False
        else:
            dynamic_lacp_list = re.findall('\d+[,\r]',rtn_str)
            
        if [] != dynamic_lacp_list:
            self.info_show(log_node_fail, log_dynamic_lacp_notexisted_fail%(self.get_ne_ip(0)))
            self.info_show(log_node_summary, log_summary_fail%(self.get_ne_ip(0)))
            return False
        else:
            self.info_show(log_node_success, log_dynamic_lacp_notexisted_success%(self.get_ne_ip(0)))             
            return True
            
    def set_system_mac(self):
        if string.atoi(self.inventory_mac.lower()[4:],16) != string.atoi(self.console_mac.lower()[4:],16)-1:
            self.info_show(log_node_fail, log_mac_verify_fail%(self.get_ne_ip(0)))
            self.info_show(log_node_summary, log_summary_fail%(self.get_ne_ip(0)))
            return False
        else:
            system_mac = self.inventory_mac[0:2]+":"+self.inventory_mac[2:4]+":"+self.inventory_mac[4:6]+":"+self.inventory_mac[6:8]+":"+self.inventory_mac[8:10]+":"+self.inventory_mac[10:12]
            set_cmd = '$.dbgcli.0.Cmd "updateasyn valid 1 LsrCfg {SysMac(%s)} LsrId=%s"'%(system_mac,r"'\\\lsrid=1'")
            rtn_str = self.tnxxx.send_rtn_str(set_cmd, self.get_ne_ip(0), 0, MTN_PORT)
            if [] == re.findall('success', rtn_str):         
                self.info_show(log_node_fail, log_set_system_mac_fail%(self.get_ne_ip(0)))
                self.info_show(log_node_summary, log_summary_fail%(self.get_ne_ip(0)))
                return False
            else:
                self.info_show(log_node_success, log_set_system_mac_success%(self.get_ne_ip(0),system_mac))                
            
    def _execute(self):                        
        self.info_init()
        
        worktime = str(datetime.datetime.now())
        self.worktime = worktime[:4]+worktime[5:7]+worktime[8:10]+'_'+worktime[11:13]+worktime[14:16]+worktime[17:19]
        
        self.iplistfile = self.options.cfgfile
        self.set = self.options.set
        self.check = self.options.check
        self.work_path = os.getcwd()
        
        ip_list = self.get_iplist()         
        
        for ip in ip_list:            
            self.set_ne_ip(0, ip)  
            self.master_opca = 0
            self.system_mac = ""
            self.inventory_mac = ""
            self.console_mac = ""
            self.tnxxx.disconnect()
            
            if False == self.get_master_opca():
                continue
            
            if False == self.get_system_mac():
                continue

            if False == self.get_inventory_mac():
                continue
            
            if False == self.get_console_mac():
                continue
            
            self.get_zebos_mac()
            
            if "enable" == self.check:
                self.check_unexpected_mac()
                
            if False == self.if_dynamic_trunk_notexisted():
                continue
                
            if "enable" == self.set:
                if False == self.set_system_mac():
                    continue
                            
            self.info_show(log_node_summary, log_summary_success%(ip))              
           
        worktime = str(datetime.datetime.now())
        self.worktime_end = worktime[:4]+worktime[5:7]+worktime[8:10]+'_'+worktime[11:13]+worktime[14:16]+worktime[17:19]
        
        self.info_show(log_node_summary, "The system mac operation begin time %s "%(self.worktime))
        self.info_show(log_node_summary, "The system mac operation end time %s "%(self.worktime_end))
        
        ip = '0.0.0.0'
        self.info_file_save(ip) 
        return True
    
if __name__ == "__main__" :
    case = TestCase()
    case.execute()